/**
  ETFRoot project, Anyang Normal University && IMP-CAS
  \class ETFPID
  \brief class for particle identification. This class takes tracks on both sides
  of the dipole magnet to extract particle A/Z, and particle velocity beta.
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-11-10
  \date 2021-12-15 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-11-10   <td>Asia Sun    <td>file created                  </tr>
  </table>

  \copyright Copyright (c) 2021 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#ifndef ETFPID_h
#define ETFPID_h

#include <TNamed.h>

class TGraph;
class TLegend;
class ETFVMEEvent;

class ETFPID : public TNamed{
public:
  ETFPID();
  virtual ~ETFPID();

  virtual void Initialize();
  virtual void Reset(){ Initialize(); }
  /// propogate the particle in the dipole magnet to meet the tracks given by the DCs
  /// currently and usually a uniform magnetic field is assumed, as it is both
  /// appropriate and efficient
  /// \param tof2: from the target to TOFWall
  /// \param pIn[0-3]: {k1_Ta, k2_Ta, b1_Ta, b2_Ta}
  /// \param pOut[0-3]: {k1, k2, b1, b2}
  virtual bool Fly(const double *pIn, const double *pOut, double tof2);
  /// the same fly, but collecting information using singleton classes in ETFAna
  /// \param istof2: whether we only call fly to calculate tof2
  virtual bool Fly(bool istof2 = false);
  bool HasFlied() const{ return fHasFlied; }

  void SetMagneticIntensity(double b){ SetB(b); } ///< in Tesla
  void SetB(double b){ kB = b; }
  virtual void ConstructGraph(); ///< update fCurve
  virtual void Draw();

  ///@{ fragment identification
  double tof2() const{ return ftof2; } ///< time-of-flight from Tstop to TOFWall
  double GetBeta() const{ return fBeta; }
  double beta() const{ return fBeta; }
  double gamma() const{ return fGamma; }
  double bg() const{ return fBG; } // beta*gamma
  void SetdE1(double d){ fdE1 = d; }
  double GetdE1() const{ return fdE1; }
  double dE1() const{ return fdE1; }
  double GetAoZ() const{ return fAoZ; }
  double aoz() const{ return fAoZ; }
  double GetPoZ() const{ return fPoZ; }
  double poz() const{ return fPoZ; }
  double GetBrho() const{ return fBrho; }
  double brho() const{ return fBrho; }
  double dx2() const; // x2arr[0] - x2arr[1]
  ///@}

  ///@{ incident particle identification
  double tof1() const{ return ftof1; } ///< time-of-flight from Tstart to Tstop
  double GetBeta0() const{ return fBeta0; }
  double beta0() const{ return fBeta0; }
  double gamma0() const{ return fGamma0; }
  double bg0() const{ return fBG0; } // beta0*gamma0
  void SetdE0(double d){ fdE0 = d; }
  double GetdE0() const{ return fdE0; }
  double dE0() const{ return fdE0; }
  ///@}

  ///@{ pile ups
  virtual void SetPileUp(ETFVMEEvent *vme);
  void Setdsca11(int d){ fdsca11 = d; }
  void Setdsca4(int d){ fdsca4 = d; }
  int dsca11() const{ return fdsca11; }
  int dsca4() const{ return fdsca4; }
  ///@}

  ///@{ calculate parallel momentum and its relevant uncertainties
  bool costh(); ///< \retval false: not eligible for calculating pozpl
  double cospl() const{ return fCospl; }
  double dcospl() const{ return fdCospl; }
  double pozpl() const{ return fPoZpl; }
  double dpozpl() const{ return fdPoZpl; }
  double BGC() const{ return fBGC; }
  double dBGC() const{ return fdBGC; }
  ///@}

  virtual void Print();

  ClassDef(ETFPID, 1); ///< particle identification

protected:
  static double kB; //! ///< the effective magnetic intensity of the dipole magnet, in Tesla
  bool fHasFlied; //! ///< whether PID has been done

  /// pileup stamp: dsca11: each tstop signal within two accepted triggers is
  /// followed by a 10us window. The tstop signals within the window would be counted
  /// and accumulated as dsca11. The window-generating tstop signal counts are excluded
  /// from dsca11. So that dsca11==0 ensures that tstop signals (almost can be treatd
  /// as particles) within two accepted triggers are all 10-us apart from each other.
  /// dsca4: counts of tstop signals between two consecutive accepted triggers,
  /// i.e. differing from dsca11 in that the trigger-generating tstop counts are also
  /// included, so that dsca11==0 ensures that no tstop signals are found with the
  /// two triggers.
  int fdsca11, fdsca4;

  ///@{ variables for incident-particle identification
  double ftof1; ///< time-of-flight from Tstart to Tstop
  double fBeta0, fGamma0, fBG0; ///< beta0: for incident particles
  double fdE0; ///< energy deposit for incident particles
  ///@}

  ///@{ variables for fragment identification
  double fBeta, fGamma, fBG; ///< beta: for fragments
  double fAoZ; ///< A/Z: a over z
  double fPoZ, fBrho; // p/Z: p over z; brho: B*rho
  double fTrkLenT; ///< total track length: from Tstop to TOFWall
  /// x2: abscissa of Mag exit point from real trk and calculated arc
  /// as a PID estimator; 0-1: real-calcu
  double fX2Arr[2];
  double ftof2; ///< time-of-flight from Tstop to TOFWall
  double ftof2_ofst; //! ///< calibration constants for tof2: tof2 += tof2_ofst
  double fdE1; ///< energy deposit for fragments
  // double fcost; ///< cos(theta_c-theta_p)
  // double fdcdkp, fdcdkc; ///< dcost/dkp, dcost/dkc, p,c: proj, core
  //@}

  ///@{ for visualization purposes
  TGraph *fGCurve; //! ///< the curve in the dipole magnet
  TLegend *fGLegend; //! ///< mark the aoz of the event
  double fXO, fZO; //! ///< center of the arc, used to draw the curve
  double fRho; ///< radius of the arc, used to draw the curve
  /// @) for visualization purposes

  ///@{ parallel momentum and its relevant uncertainties
  /// cos<n0,n1> (vec. of inci. v.s. exit) & err & parallel poz component
  double fCospl, fdCospl, fPoZpl, fdPoZpl;
  double fBGC, fdBGC; ///< beta*gamma*u*cospl & err, pozpl = BGC*aoz
  ///@}
};

#endif
